package com.qiaofang.applet.service.member.service.impl;

import cn.hutool.core.util.XmlUtil;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.client.result.DeleteResult;
import com.qiaofang.applet.common.base.MongoBaseService;
import com.qiaofang.applet.common.util.RedisKeyUtil;
import com.qiaofang.applet.common.util.RedisUtil;
import com.qiaofang.applet.service.member.domain.WxFollowUsers;
import com.qiaofang.applet.service.member.repository.WxFollowUsersRepository;
import com.qiaofang.applet.service.member.service.WxFollowUsersService;
import com.qiaofang.applet.service.member.service.dto.PullWxFollowDto;
import com.qiaofang.applet.service.other.domain.Corporation;
import com.qiaofang.applet.service.other.repository.CorporationRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Map;

/**
 * @Author: youqing.yang
 * @Create: 2021/06/22 10:28
 * @Description:
 **/
@Slf4j
@Service
public class WxFollowUsersServiceImpl extends MongoBaseService<WxFollowUsers, String> implements WxFollowUsersService {

    private final WxFollowUsersRepository repository;

    private final static String UN_SUBSCRIBE = "unsubscribe";

    private final static String SUBSCRIBE = "subscribe";

    /**
     * 获取token
     * GET
     * https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
     */
    private static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

    /**
     * 获取单个用户详情
     * GET
     * https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId
     */
    private static final String USER_URL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";


    @Autowired
    public WxFollowUsersServiceImpl(WxFollowUsersRepository repository) {
        super(repository);
        this.repository = repository;
    }

    @Autowired
    private RedisUtil redisUtil;

    protected RestTemplate restTemplate;

    {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(30000);
        requestFactory.setReadTimeout(30000);
        restTemplate = new RestTemplate(requestFactory);
    }

    @Autowired
    private CorporationRepository corporationRepository;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public String getAccessToken(PullWxFollowDto paramDto) {
        String wxAccessTokenKey = RedisKeyUtil.getWxAccessTokenKey(paramDto.getCorporationCode());
        Object obj = redisUtil.get(wxAccessTokenKey);
        if (obj != null) {
            return (String) obj;
        }
        String token_url = TOKEN_URL.replace("APPID", paramDto.getAppId()).replace("APPSECRET", paramDto.getAppSecret());
        //token失效时间2h
        JSONObject tokenObject = null;
        try {
            tokenObject = restTemplate.getForObject(token_url, JSONObject.class);
        } catch (RestClientException e) {
            log.error("获取公众号token error：{}", e);
        }
        log.info("get tokenObject:{},params:{}", tokenObject, JSONObject.toJSONString(paramDto));
        String access_token = null;
        if (tokenObject != null) {
            access_token = tokenObject.getString("access_token");
            log.info("access_token：{}", access_token);
            redisUtil.set(RedisKeyUtil.getWxAccessTokenKey(paramDto.getCorporationCode()), access_token, 7200);
        }
        return access_token;
    }

    @Override
    public void monitorWxFollowEvent(String corporationCode, HttpServletRequest request) {

        Map<String, Object> stringObjectMap = null;
        try {
            int len = request.getContentLength();
            System.out.println("数据流长度:" + len);
            //获取HTTP请求的输入流
            InputStream is = request.getInputStream();
            //已HTTP请求输入流建立一个BufferedReader对象
            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            //读取HTTP请求内容
            String buffer;
            StringBuffer sb = new StringBuffer();
            while ((buffer = br.readLine()) != null) {
                //在页面中显示读取到的请求参数
                sb.append(buffer);
            }
            if (StringUtils.isBlank(sb.toString())) {
                return;
            }
            stringObjectMap = XmlUtil.xmlToMap(sb.toString());
        } catch (UnsupportedEncodingException ex) {
            log.error("UnsupportedEncodingException error:{}", ex);
        } catch (IOException ex) {
            log.error("IOException error:{}", ex);
        }
        log.info("stringObjectMap:{}", JSONObject.toJSONString(stringObjectMap));
        //这里是为了区分其他一些事件
        if (stringObjectMap.get("Event") == null) {
            return;
        }
        if (StringUtils.equals(stringObjectMap.get("Event").toString(), UN_SUBSCRIBE) || StringUtils.equals(stringObjectMap.get("Event").toString(), SUBSCRIBE)) {
            //先看是关注还是取关
            if (StringUtils.equals(stringObjectMap.get("Event").toString(), UN_SUBSCRIBE)) {
                //取关直接删除
                log.info("{}：公司公众号有取消关注：{}", corporationCode, JSONObject.toJSONString(stringObjectMap));
                DeleteResult remove = mongoTemplate.remove(new Query(Criteria.where("corporationCode").is(corporationCode).and("openid").is(stringObjectMap.get("FromUserName").toString())), WxFollowUsers.class);
                log.info("取消关注数：", remove.getDeletedCount());
                return;
            }

            Corporation corporation = corporationRepository.findOneByCorporationCode(corporationCode);
            if (corporation == null) {
                log.info("微信公众号关注事件异常，查无集团:{}", corporationCode);
                return;
            }

            PullWxFollowDto pullWxFollowDto = PullWxFollowDto
                    .builder()
                    .corporationCode(corporationCode)
                    .appId(corporation.getOaAppId())
                    .appSecret(corporation.getOaAppSecret())
                    .build();
            String accessToken = getAccessToken(pullWxFollowDto);
            String userUrl = USER_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", stringObjectMap.get("FromUserName").toString());

            JSONObject userObject = null;
            try {
                userObject = restTemplate.getForObject(userUrl, JSONObject.class);
            } catch (RestClientException e) {
                log.error("获取单个公众号用户异常:{}", e);
            }
            if (userObject == null) {
                return;
            }
            WxFollowUsers wxFollowUsers = JSONObject.parseObject(userObject.toJSONString(), WxFollowUsers.class);
            wxFollowUsers.setCorporationCode(corporationCode);
            log.info("{}：公司公众号新增关注：{}", corporationCode, JSONObject.toJSONString(wxFollowUsers));
            save(wxFollowUsers);
        }
        return;
    }
}
